﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using Rabbit.Model;
using System.Diagnostics;
using System.Windows.Forms;

namespace Rabbit.Utils
{ 
   public  class HotKeyHelper
    {
        #region Dll Import

        [System.Runtime.InteropServices.DllImport("user32")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint controlKey, uint virtualKey);

        [System.Runtime.InteropServices.DllImport("user32")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id); 
        #endregion

       /// <summary>
       /// the event that when the hotkey clicked
       /// </summary>
        public Action OnHotKeyClicked = null;   

        static Dictionary<int, HotKeyHelper> KeyPair = new Dictionary<int, HotKeyHelper>();         //热键哈希表

        private const int WM_HOTKEY = 0x0312;       // 热键消息编号
        static System.Windows.Interop.HwndSource source;
        static IntPtr handle;
        public HotKeyHelper(Window window, ModifierKeys modifierKeys,uint KeyCode)
        {
            handle = new WindowInteropHelper(window).Handle;
            if (handle == IntPtr.Zero)
            {
                throw new Exception("please register hot key after the window loaded");
            }

            int keyId = (int)modifierKeys + (int)KeyCode * 10;

            if (HotKeyHelper.KeyPair.ContainsKey(keyId))
            {
                throw new SameHotKeyHasRegisteredException();
            }

            //register hot key
            if (!RegisterHotKey(handle, keyId, (uint)modifierKeys, KeyCode))
            {
                throw new RegisterHotKeyFailedException();
            }

            //add hook
            if (HotKeyHelper.KeyPair.Count == 0 && source == null)
            { 
                source = System.Windows.Interop.HwndSource.FromHwnd(handle);
                if (source == null) return;
                source.AddHook(HotKeyHook);
            }
             
            //add this key to the dictionary
            HotKeyHelper.KeyPair.Add(keyId, this);
        }
        
        static private IntPtr HotKeyHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            //Debug.Print("msg:" + msg + "\t HotKey:" + WM_HOTKEY);
            if (msg == WM_HOTKEY)
            {
                HotKeyHelper hk = (HotKeyHelper)HotKeyHelper.KeyPair[(int)wParam];
                if (hk.OnHotKeyClicked != null) hk.OnHotKeyClicked();
            }
            return IntPtr.Zero;
        }

        public static void Unregister(ModifierKeys modifierKeys,uint keyCode)
        {
            int keyID = (int)modifierKeys + (int)keyCode * 10;
            UnregisterHotKey(handle, keyID);
            HotKeyHelper.KeyPair.Remove(keyID);
        }
    } 
}